﻿#region License
/* ---------------------------------------------------------------- *
 *
 * This file is part of the Xcoordination Application Space
 * ("XcoAppSpace") http://www.xcoordination.com
 *
 * Copyright (C) 2009 Xcoordination http://www.xcoordination.com
 *
 * XcoAppSpace is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General
 * Public License as published by the Free Software Foundation.
 *
 * XcoAppSpace is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses/
 * or write to the Free Software Foundation, Inc., 51 Franklin
 * Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * ---------------------------------------------------------------- */
#endregion

#if !MF

using System;
using XcoAppSpaces.Core.Ports;

namespace XcoAppSpaces.Contracts.Messaging
{
	/// <summary>
	/// Provides thread-based context information needed for serialization and deserialization of ports and portsets.
	/// </summary>
	public class SerializationContext : IDisposable
	{

#if PocketPC
		private static readonly LocalDataStoreSlot StoreSlot = Thread.AllocateDataSlot(); //Compact Framework doesnt support ThreadStatic!!

		/// <summary>
		/// The serialization context for the current thread.
		/// </summary>
		public static SerializationContext Current
		{
			get { return (SerializationContext)Thread.GetData(StoreSlot); }
		}
#else
		[ThreadStatic]
		private static SerializationContext current = null;

		/// <summary>
		/// The serialization context for the current thread.
		/// </summary>
		public static SerializationContext Current
		{
			get { return current; }
		}
#endif

		/// <summary>
		/// Delegate that can be used to send messages to remote space instances.
		/// </summary>
		public Action<MessageToSend> MessageProcessor { get; private set; }

		/// <summary>
		/// The local space address.
		/// </summary>
		public string LocalAddress { get; private set; }

		/// <summary>
		/// The name of the communication service where the message is sent/received.
		/// </summary>
		public string CurrentCommServiceName { get; private set; }

        private readonly Func<IPort, Guid> registerPort;

		/// <summary>
		/// Creates a new SerializationContext and assigns it to the SerializationContext.Current property of the current thread.
		/// </summary>
		/// <param name="registerPort">Delegate to register a port at the local space instance.</param>
		/// <param name="messageProcessor">Delegate that can be used to send messages to remote space instances.</param>
		/// <param name="localAddress">The local space address.</param>
		/// <param name="currentCommServiceName">The name of the communication service where the message is sent/received.</param>
		public SerializationContext(Func<IPort, Guid> registerPort, Action<MessageToSend> messageProcessor, string localAddress, string currentCommServiceName)
		{
            this.registerPort = registerPort;
			this.MessageProcessor = messageProcessor;
            this.LocalAddress = localAddress;
            this.CurrentCommServiceName = currentCommServiceName;
#if PocketPC
			Thread.SetData(StoreSlot, this);
#else
			current = this;
#endif
		}

		/// <summary>
		/// Registers a port at the local space instance, and assigns a unique id to this port.
		/// This allows remote space instances to send messages to this port, if they know its id. 
		/// </summary>
		/// <param name="port">The port to be registered.</param>
		/// <returns>Unique id that has been assigned to the port.</returns>
        public Guid RegisterPort(IPort port)
        {
            return registerPort(port);
        }

		/// <summary>
		/// Disposes the SerializationContext and removes it from the current thread.
		/// </summary>
	    public void Dispose()
		{
#if PocketPC
			Thread.SetData(StoreSlot, null);
#else
			current = null;
#endif
		}
	}
}

#endif
